#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QMessageBox>
#include <QTimer>
#include <QDateTime>
#include <QFileDialog>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    this->setWindowIcon(QIcon(":/jackson.png"));
    this->setWindowTitle("Enimapad串口助手");
    //加入串口控制对象
    serialPort = new QSerialPort(this);
    //发送按钮初始设为失能
    ui->pushButton_send->setEnabled(false);
    ui->comboBox_baudRate->setCurrentText("9600");
    ui->comboBox_dataSize->setCurrentText("8");
    //检测端口定时器
    this->startTimer(1000);

    //定时自动发送功能
    timerSend = new QTimer(this);
    connect(timerSend, &QTimer::timeout, [=](){
        on_pushButton_send_clicked();
    });
    //每500ms更新系统时间
    timerSystem = new QTimer(this);
    timerSystem->start(500);
    connect(timerSystem, &QTimer::timeout, [=](){
        QDateTime dateTime = QDateTime::currentDateTime();
        //获取日期
        QDate date = dateTime.date();
        int year = date.year();
        int month = date.month();
        int day = date.day();
        //获取时间
        QTime time = dateTime.time();
        int hour = time.hour();
        int minute = time.minute();
        int second = time.second();

        QString myTime = "Time：";
        myTime += QString::number(year) + "-"
               + QString::number(month) + "-"
               + QString::number(day) + " "
               + QString::number(hour) + ":"
               + QString::number(minute) + ":"
               + QString::number(second);
        ui->label_time->setText(myTime);//打印时间
    });

}

Widget::~Widget()
{
    delete ui;
}

//重写定时器事件用于 检测端口
void Widget::timerEvent(QTimerEvent *event)
{
    //检查端口号
    QVector<QString> temp;
    for(const QSerialPortInfo& info : QSerialPortInfo::availablePorts())
    {
        temp.push_back(info.portName());
    }
    std::sort(temp.begin(), temp.end());
    //端口发生变化 则更新端口
    if(temp != comPorts)
    {
        ui->comboBox_serialNum->clear();
        this->comPorts = temp;
        for(auto& port : comPorts)
        {
            ui->comboBox_serialNum->addItem(port);
        }
    }

    //检查数据模式
}

//清空接收区数据
void Widget::on_pushButton_clearReceive_clicked()
{
    ui->plainTextEdit_receive->clear();
}
//清空发送区数据
void Widget::on_pushButton_clearSend_clicked()
{
    ui->plainTextEdit_send->clear();
}
//打开(关闭)串口按钮
void Widget::on_pushButton_serial_clicked()
{
    QString text = ui->pushButton_serial->text();

    if(text == "打开串口")
    {
        if(ui->comboBox_serialNum->currentText() == "")
        {
            QMessageBox::information(this, "提示", "串口打开失败，没有搜索到串口");

        }
        else
        {
            //接收数据
            USART();
        }
    }
    else
    {
        //打开配置相关按钮
        ui->comboBox_serialNum->setEnabled(true);
        ui->comboBox_baudRate->setEnabled(true);
        ui->comboBox_dataSize->setEnabled(true);
        ui->comboBox_stopSize->setEnabled(true);
        ui->comboBox_checkSize->setEnabled(true);
        ui->comboBox_encodeReceive->setEnabled(true);
        ui->comboBox_encodeSend->setEnabled(true);
        ui->spinBox_time->setEnabled(true);

        ui->pushButton_serial->setText("打开串口");
        ui->pushButton_send->setEnabled(false); //禁止发送
        ui->pushButton_serial->setStyleSheet("QPushButton { background-color: rgb(225, 225, 225);"
                                             "border: 0); }");

        serialPort->close();
    }
}

//配置串口及接收数据
void Widget::USART()
{
    QSerialPort::BaudRate Baud;//波特率
    QSerialPort::DataBits Data;//数据位
    QSerialPort::StopBits Stop;//停止位
    QSerialPort::Parity Check; //校验位

    QString baud = ui->comboBox_baudRate->currentText();
    QString data = ui->comboBox_dataSize->currentText();
    QString stop = ui->comboBox_stopSize->currentText();
    QString check = ui->comboBox_checkSize->currentText();

    if(baud == "4800") Baud = QSerialPort::Baud4800;
    else if(baud == "9600") Baud = QSerialPort::Baud9600;
    else if(baud == "19200") Baud = QSerialPort::Baud19200;
    else if(baud == "115200") Baud = QSerialPort::Baud115200;

    if(data == "8") Data = QSerialPort::Data8;
    else if(data == "7") Data = QSerialPort::Data7;
    else if(data == "6") Data = QSerialPort::Data6;
    else if(data == "5") Data = QSerialPort::Data5;

    if(stop == "1") Stop = QSerialPort::OneStop;
    else if(stop == "1.5") Stop = QSerialPort::OneAndHalfStop;
    else if(stop == "2") Stop = QSerialPort::TwoStop;

    if(check == "无") Check = QSerialPort::NoParity;
    else if(check == "奇校验") Check = QSerialPort::OddParity;
    else if(check == "偶校验") Check = QSerialPort::EvenParity;

    serialPort->setBaudRate(Baud);
    serialPort->setDataBits(Data);
    serialPort->setStopBits(Stop);
    serialPort->setParity(Check);
    serialPort->setPortName(ui->comboBox_serialNum->currentText());

    bool ret = serialPort->open(QSerialPort::ReadWrite);//打开串口读写模式
    if(!ret)//串口打开失败
    {
        QMessageBox::critical(this, "串口打开失败！", "请确认串口是否被占用");
    }
    else//打开成功
    {
        //关闭配置相关按钮
        ui->comboBox_serialNum->setEnabled(false);
        ui->comboBox_baudRate->setEnabled(false);
        ui->comboBox_dataSize->setEnabled(false);
        ui->comboBox_stopSize->setEnabled(false);
        ui->comboBox_checkSize->setEnabled(false);
        ui->comboBox_encodeReceive->setEnabled(false);
        ui->comboBox_encodeSend->setEnabled(false);
        ui->spinBox_time->setEnabled(false);

        ui->pushButton_serial->setText("关闭串口");
        ui->pushButton_send->setEnabled(true);  //可以发送
        ui->pushButton_serial->setStyleSheet("QPushButton { background-color: rgb(204, 228, 247);"
                                             "border: 1px solid rgb(139, 162, 131); }");

        //接收数据
        connect(serialPort, &QSerialPort::readyRead, [=](){
            QByteArray arr = serialPort->readAll();//读取串口数据
            QString text;
            //十六进制接收
            if(ui->comboBox_receiveMode->currentText() == "HEX")
            {
                QString str1 = arr.toHex().toUpper();//转换为十六进制大写
                QString str2;
                //添加空格  一个字节由两个十六进制数字表示
                for(int i = 0; i < str1.size(); i += 2)
                {
                    str2 += str1.mid(i, 2) + " ";
                }
                text = str2;//以字符串形式存储到text中
            }
            else//文本模式接收
            {
                text = QString(arr);//读到的内容直接打印输出
            }

            ui->plainTextEdit_receive->insertPlainText(text);
            //光标移到末尾 自动更新页面
            ui->plainTextEdit_receive->moveCursor((QTextCursor::End));

            //更新数据总接收长度
            readCountTotal += arr.size();
            ui->label_received->setText("Received：" + QString::number(readCountTotal));   
        });
    }
}

//发送数据
void Widget::on_pushButton_send_clicked()
{
    QString text = ui->plainTextEdit_send->toPlainText();//获取文本框内容
    QByteArray arr = text.toLocal8Bit();//转换为GB2312编码 或者Utf8()转换为UTF8编码

    //十六进制发送
    if(ui->comboBox_sendMode->currentText() == "HEX")
    {
        int alnum = 0;//记录十六进制数字长度 只能为偶数（2个十六进制数字表示1个字节）
        //判断是否符合十六进制 有一个字母不符合则发送失败
        for(auto ch : arr)
        {
            if(ch != ' ' && !std::isxdigit(ch))
            {
                ui->label_status->setText("Input Error!");
                return;
            }
            if(ch != ' ') alnum++;
        }
        //十六进制字符串长度不是偶数 发送失败
        if(alnum % 2 == 1)
        {
            ui->label_status->setText("Input Error!");
            return;
        }
        arr = QByteArray::fromHex(arr);//将十六进制字符串转换为对应的字节序列
    }
    //发送换行
    if(ui->checkBox_newline->checkState() == Qt::Checked)
    {
        arr.append("\r\n");
    }
    //更新发送数据总数
    int writeCount = serialPort->write(arr);
    if(writeCount == -1)
    {
        ui->label_status->setText("Send Error!");
    }

    else
    {
        writeCountTotal += writeCount;
        ui->label_status->setText("Send Ok!");
        ui->label_sent->setText("Sent：" + QString::number(writeCountTotal));
    }
}

//是否打开定时发送
void Widget::on_checkBox_send_clicked(bool checked)
{
    if(checked)//定时发送功能打开
    {
        timerSend->start(ui->spinBox_time->text().toInt());//开启定时器
        ui->spinBox_time->setEnabled(false);        //关闭调节发送时间间隔功能
        ui->plainTextEdit_send->setReadOnly(true);//发送区不可写
    }
    else
    {
        timerSend->stop();//关闭定时器
        ui->spinBox_time->setEnabled(true);        //可以调节发送时间
        ui->plainTextEdit_send->setReadOnly(false);//发送区恢复可写状态
    }
}


//保存接收区内容到文件中
void Widget::on_pushButton_saveFile_clicked()
{
    QString path = QFileDialog::getSaveFileName(this);
    QFile file(path);
    if(!file.open(QFile::WriteOnly))//打开文件失败
    {
        ui->label_sent->setText("文件保存失败！");
        return;
    }
    file.write(ui->plainTextEdit_receive->toPlainText().toUtf8());//写文件
    file.close();
}
//读取文件内容到接收区中
void Widget::on_pushButton_openFile_clicked()
{
    QString path = QFileDialog::getOpenFileName(this);
    QFile file(path);
    if(!file.open(QFile::ReadOnly))
    {
        ui->label_sent->setText("文件打开失败！");
        return;
    }
    ui->plainTextEdit_receive->setPlainText(QString(file.readAll()));
    file.close();
}

